import type { App } from 'antd';
import { groupBy, keyBy } from 'lodash-es';
import { action, observable } from 'mobx';
import { useLocalObservable } from 'mobx-react-lite';
import io from 'socket.io-client';

import { DrawerHookAPI } from '@/components/useFeedback/drawer';
import { ModalHookAPI } from '@/components/useFeedback/modal';

import { securityLogout, securitySelf } from '@/services/base/denglumokuaidenglujiekou';
import { sysMessageRecordUnreadCount } from '@/services/base/jichumokuaixiaoxijilujiekou';
import { systemConfigList } from '@/services/base/jichumokuaixitongpeizhixinxijiekou';
import { dicInfoAll } from '@/services/base/jichumokuaizidianxinxijiekou';
import { parseSrc } from '@/utils';
import { request } from '@/utils/api';

export let socket: ReturnType<typeof io> | null = null;

export const store = observable({
  /** 用户信息 */
  user: null as null | User,
  /** 是否登录 */
  get isLogin() {
    return !!this.user;
  },
  get displayName() {
    return this.user?.extendData?.user?.fullName || this.user?.extendData?.user?.username;
  },
  get avatar() {
    return parseSrc(this.user?.extendData?.user?.photoUrl);
  },
  /** 角色 */
  role: [] as string[],
  /** 路由权限 */
  permissions: [] as string[],

  /** 未读消息数 */
  unreadCount: 0,

  /** antd app 实例 */
  app: null as null | ReturnType<typeof App.useApp>,

  modal: {} as ModalHookAPI,
  drawer: {} as DrawerHookAPI,

  /** 字典 */
  dict: {} as Record<string, BASE.DicInfoVO[]>,
  /** 系统配置 */
  config: {} as Record<string, BASE.SystemConfig>,

  /** iconify图标 */
  icon: {} as Record<string, Record<string, string[]>>,

  /** 根据token获取用户信息 */
  getUserInfoByToken: action(async (token: string): Promise<BASE.IUser | undefined> => {
    const [err, userInfo] = await securitySelf({
      tupleResponse: true,
      skipErrorHandler: true,
      headers: {
        token
      }
    });

    if (err || !userInfo?.data) {
      // 移除缓存
      localStorage.removeItem('token');

      return;
    }

    store.user = userInfo.data as User;
    store.role = userInfo.data.roles || [];
    store.permissions = userInfo.data.pages || [];

    request.defaults.headers.token = request.defaults.headers.token || token;

    store.getUnreadCount();
    store.initSocket(userInfo.data as User, token);
    store.getConfig();
    store.getDict();

    return userInfo.data;
  }),
  /** 退出登录 */
  logout: action(async () => {
    await securityLogout({
      tupleResponse: true,
      skipErrorHandler: true,
      timeout: 3 * 1000
    });

    delete request.defaults.headers.token;
    store.user = null;
    store.role = [];
    store.permissions = [];
    window.localStorage.removeItem('token');

    if (socket?.connected) {
      socket.disconnect();
      socket = null;
    }
  }),
  /** 获取未读消息数 */
  getUnreadCount: action(async () => {
    store.unreadCount = (await sysMessageRecordUnreadCount()).data || 0;
  }),
  /** 初始化socket */
  initSocket: action((user: User, token: string) => {
    if (socket?.connected) {
      return;
    }
    const host =
      process.env.NODE_ENV === 'development' ? 'http://10.36.16.30' : 'http://10.20.7.100';
    socket = io(`${host}:10066`, {
      path: '/socket.io',
      transports: ['websocket'],
      query: {
        userId: user.id,
        token
      }
    });

    socket.on('error_notification', (data: unknown) => {
      console.log('错误通知', data);
      store.getUnreadCount();
    });

    socket.on('system_notification', (data: unknown) => {
      console.log('系统消息', data);
      store.getUnreadCount();
    });

    socket.on('connect', () => {
      console.log('socket connect');
    });

    socket.on('disconnect', (e: unknown) => {
      console.log('socket disconnect', e);

      if (store.isLogin) {
        socket?.disconnect();
        socket?.connect();
      }
    });

    socket.on('connect_error', (e: unknown) => {
      console.log('socket connect_error', e);
      if (store.isLogin) {
        socket?.disconnect();
        socket?.connect();
      }
    });
  }),
  /** 获取字典 */
  getDict: action(async () => {
    const dict = (await dicInfoAll()).data || {};

    store.dict = groupBy(dict, 'dicCode');
  }),
  /** 获取系统配置 */
  getConfig: action(async () => {
    const res = await systemConfigList({
      configModule: '网站配置'
    });

    if (res.data) {
      store.config = keyBy(res.data, 'configName');
    }
  }),
  /** 权限校验 */
  auth: action((targetAuth?: string[]): boolean => {
    if (Array.isArray(targetAuth)) {
      return targetAuth.some((auth) => {
        store.permissions.includes(auth);
      });
    }

    return true;
  })
});

export const useStore = () => useLocalObservable(() => store);
